package com.digitaldreamers.framework.scene.background;

/**
 * http://www.andengine.org/forums/gles2/vertical-parallax-with-gles2-t6806.html
 * */

import java.util.ArrayList;

import org.andengine.engine.camera.Camera;
import org.andengine.entity.IEntity;
import org.andengine.entity.scene.background.ParallaxBackground;
import org.andengine.opengl.util.GLState;

public class VerticalParallaxBackground extends ParallaxBackground {
	public static final int SCROLL_DOWN = -1;
	public static final int SCROLL_UP = 1;
	// ===========================================================
	// Constants
	// ===========================================================

	// ===========================================================
	// Fields
	// ===========================================================

	private final ArrayList<VerticalParallaxEntity> mParallaxEntities;
	private int mParallaxEntityCount;
	protected float mParallaxValue;

	// ===========================================================
	// Constructors
	// ===========================================================

	public VerticalParallaxBackground(float pRed, float pGreen, float pBlue) {
		super(pRed, pGreen, pBlue);
		mParallaxEntities = new ArrayList<VerticalParallaxEntity>();
	}

	// ===========================================================
	// Getter & Setter
	// ===========================================================

	public void setParallaxValue(final float pParallaxValue) {
		mParallaxValue = pParallaxValue;
	}

	// ===========================================================
	// Methods for/from SuperClass/Interfaces
	// ===========================================================

	@Override
	public void onDraw(final GLState pGLState, final Camera pCamera) {
		super.onDraw(pGLState, pCamera);

		final float parallaxValue = mParallaxValue;
		final ArrayList<VerticalParallaxEntity> parallaxEntities = mParallaxEntities;
		// Log.d("VAPB", "VAPB onDraw pre entity");
		for (int i = 0; i < mParallaxEntityCount; i++) {
			parallaxEntities.get(i).onDraw(pGLState, pCamera, parallaxValue);
		}
	}

	// ===========================================================
	// Methods
	// ===========================================================

	public void attachVerticalParallaxEntity(final VerticalParallaxEntity pParallaxEntity) {
		mParallaxEntities.add(pParallaxEntity);
		mParallaxEntityCount++;
	}

	public boolean detachVerticalParallaxEntity(final VerticalParallaxEntity pParallaxEntity) {
		mParallaxEntityCount--;
		final boolean success = mParallaxEntities.remove(pParallaxEntity);
		if (success == false) {
			mParallaxEntityCount++;
		}
		return success;
	}

	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================

	public static class VerticalParallaxEntity {
		// ===========================================================
		// Constants
		// ===========================================================

		// ===========================================================
		// Fields
		// ===========================================================

		final float mParallaxFactor;
		final IEntity mEntity;
		private int mDirection;

		// ===========================================================
		// Constructors
		// ===========================================================

		public VerticalParallaxEntity(final float pParallaxFactor, final IEntity pEntity) {
			mParallaxFactor = pParallaxFactor;
			mEntity = pEntity;
			mDirection = VerticalParallaxBackground.SCROLL_DOWN;
		}

		public VerticalParallaxEntity(final float pParallaxFactor, final IEntity pShape, int pDirection) {
			mParallaxFactor = pParallaxFactor;
			mEntity = pShape;
			mDirection = pDirection;
		}

		// ===========================================================
		// Getter & Setter
		// ===========================================================

		// ===========================================================
		// Methods for/from SuperClass/Interfaces
		// ===========================================================

		// ===========================================================
		// Methods
		// ===========================================================

		public void onDraw(final GLState pGL, final Camera pCamera, final float pParallaxValue) {

			pGL.pushModelViewGLMatrix();
			final float cameraHeight = pCamera.getHeight();
			final float shapeHeightScaled = mEntity.getWidth() * mEntity.getScaleY();
			float baseOffset = (pParallaxValue * mParallaxFactor) % shapeHeightScaled;
			while (baseOffset > 0) {
				baseOffset -= shapeHeightScaled;
			}
			pGL.translateModelViewGLMatrixf(0, (mDirection * baseOffset), 0);
			float currentMaxY = baseOffset;
			do {
				mEntity.onDraw(pGL, pCamera);
				pGL.translateModelViewGLMatrixf(0, (mDirection * shapeHeightScaled), 0);
				currentMaxY += shapeHeightScaled;
			} while (currentMaxY < (cameraHeight + shapeHeightScaled));
			// Added shapeHeightScaled to cameraHeight so the drawing flows in
			// instead of popping in.

			pGL.popModelViewGLMatrix();

		}
		// ===========================================================
		// Inner and Anonymous Classes
		// ===========================================================
	}
}